﻿using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Yitter.IdGenerator;
using Admin.NET.Core;

namespace Admin.NET.Application
{
    /// <summary>
    /// 入库管理服务
    /// </summary>
    [ApiDescriptionSettings("自己的业务", Name = "BindEntrance", Order = 100)]
    [Route("api/[Controller]")]
    public class BindEntranceService : IDynamicApiController, ITransient
    {
        private readonly IRepository<WmsArea, MasterDbContextLocator> _wmsAreaRep;
        private readonly IRepository<WmsPlace, MasterDbContextLocator> _wmsPlaceRep;
        private readonly IRepository<WmsTask, MasterDbContextLocator> _wmsTaskRep;
        private readonly IRepository<WmsContainer, MasterDbContextLocator> _wmsContainerRep;
        private readonly IRepository<WmsContainerPlace, MasterDbContextLocator> _wmsContainerPlaceRep;
        private readonly IRepository<WmsMaterial, MasterDbContextLocator> _wmsMaterialRep;
        private readonly IRepository<WmsMaterialStock, MasterDbContextLocator> _wmsMaterialStockRep;
        private readonly IRepository<WmsMaterialContainer, MasterDbContextLocator> _wmsMaterialContainerRep;

        /// <summary>
        /// 构造函数
        /// </summary>
        public BindEntranceService(
                        IRepository<WmsArea, MasterDbContextLocator> wmsAreaRep,
                        IRepository<WmsPlace, MasterDbContextLocator> wmsPlaceRep,
                        IRepository<WmsTask, MasterDbContextLocator> wmsTaskRep,
                        IRepository<WmsContainer, MasterDbContextLocator> wmsContainerRep,
                        IRepository<WmsContainerPlace, MasterDbContextLocator> wmsContainerPlaceRep,
                        IRepository<WmsMaterial, MasterDbContextLocator> wmsMaterialRep,
                        IRepository<WmsMaterialStock, MasterDbContextLocator> wmsMaterialStockRep,
                        IRepository<WmsMaterialContainer, MasterDbContextLocator> wmsMaterialContainerRep)
        {
            this._wmsAreaRep = wmsAreaRep;
            this._wmsPlaceRep = wmsPlaceRep;
            this._wmsTaskRep = wmsTaskRep;
            this._wmsContainerRep = wmsContainerRep;
            this._wmsContainerPlaceRep = wmsContainerPlaceRep;
            this._wmsMaterialRep = wmsMaterialRep;
            this._wmsMaterialStockRep = wmsMaterialStockRep;
            this._wmsMaterialContainerRep = wmsMaterialContainerRep;
        }

        /// <summary>
        /// 托盘查询组盘物料
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("getcontainer")]
        [UnifyResult(typeof(BindEntranceOutput))]
        public async Task<object> GetContainer([FromQuery] BindEntranceInput input)
        {
            var bindEntranceOutputModel = new BindEntranceOutput();

            var wmsContainer = await _wmsContainerRep.FirstOrDefaultAsync(n => n.ContainerCode == input.ContainerCode && n.ContainerStatus != ContainerStatus.JINYONG);
            if (wmsContainer == null)
            {
                var newWmsContainer = new WmsContainerDto();
                newWmsContainer.ContainerCode = input.ContainerCode;
                newWmsContainer.ContainerStatus = ContainerStatus.KOUXIAN;
                newWmsContainer.ContainerType = ContainerType.SULIAO;

                bindEntranceOutputModel.ContainerCode = input.ContainerCode;
                bindEntranceOutputModel.WmsContainer = newWmsContainer;

                if (wmsContainer != null)
                {
                    var isWmsTask = await _wmsTaskRep.AnyAsync(p => p.ContainerCode == wmsContainer.ContainerCode && p.TaskStatus != TaskStatusEnum.WANCHENG);
                    if (isWmsTask) return XnRestfulResultProvider.RESTfulMesaage("周转箱号存在未完成任务!");

                    bindEntranceOutputModel.WmsContainer = wmsContainer.Adapt<WmsContainerDto>();
                    bindEntranceOutputModel.ContainerCode = wmsContainer.ContainerCode;

                    // 周转箱号组盘状态
                    if (wmsContainer.ContainerStatus == ContainerStatus.ZUPANG)
                    {
                        bindEntranceOutputModel.WmsMaterials = await _wmsMaterialContainerRep
                            .Where(p => p.ContainerCode == wmsContainer.ContainerCode && p.BindStatus == CommonStatus.ENABLE).ProjectToType<GetMaterialContainerOutput>().ToListAsync();

                        return XnRestfulResultProvider.RESTfulResult(bindEntranceOutputModel);
                    }
                    // 周转箱号库位状态
                    if (wmsContainer.ContainerStatus == ContainerStatus.KUWEI)
                    {
                        // 查询周转箱号与库位关系
                        var wmsContainerPlace = await _wmsContainerPlaceRep.FirstOrDefaultAsync(u => u.ContainerId == wmsContainer.Id && u.ContainerCode == wmsContainer.ContainerCode);

                        if (wmsContainerPlace != null) bindEntranceOutputModel.PlaceCode = wmsContainerPlace.PlaceCode;

                        return XnRestfulResultProvider.RESTfulResult(bindEntranceOutputModel);
                    }
                }
            }
            return XnRestfulResultProvider.RESTfulResult(bindEntranceOutputModel);
        }

        /// <summary>
        /// 扫码获取物料
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetMaterial")]
        [UnifyResult(typeof(MaterialOutput))]
        public async Task<object> GetMaterial([FromQuery] GetMaterialInput input)
        {
            var material = new MaterialOutput();
            material.MaterialName = "胶合板";
            material.MaterialNo = "JHB20110101";
            material.MaterialId = 43214325321513;
            material.MaterialBatch = "DIYIPICI001";
            material.MaterialType = MaterialType.BAOZHUANGCAILIAO;
            material.InspectionMethod = MaterialInspection.MIANJIAN;
            material.MaterialSpec = "";
            material.MaterialDensity = "";
            material.MaterialUnit = "";
            material.LesWorkshopSection = LesWorkshopSection.CNC;
            return XnRestfulResultProvider.RESTfulResult(material);

        }


        /// <summary>
        ///  组盘
        /// </summary>
        /// <returns></returns>
        [HttpPost("AutoWare")]
        public async Task AutoWare(WarehousingInput input)
        {
            // 根据托盘号查询托盘号信息是否已存在
            var wmsContainer = await _wmsContainerRep.FirstOrDefaultAsync(u => u.ContainerCode == input.ContainerCode);
            if (wmsContainer == null)
            {
                // 不存在则添加托盘号信息
                wmsContainer = new WmsContainer
                {
                    ContainerCode = input.ContainerCode,
                    ContainerType = ContainerType.SULIAO,
                    ContainerStatus = ContainerStatus.KOUXIAN,
                    AssetNo = "N/A",
                    ErpNo = "N/A"
                };
                await _wmsContainerRep.InsertNowAsync(wmsContainer);
            }
            // 查询是否任务已存在
            var isExit = await _wmsTaskRep.AnyAsync(p => p.ContainerCode == wmsContainer.ContainerCode && p.TaskStatus != TaskStatusEnum.WANCHENG);
            if (isExit) throw Oops.Oh("托盘号存在未完成任务中!");

            // 查询已组盘信息
            var wmsMaterialContainerList = await _wmsMaterialContainerRep
                .Where(p => p.ContainerCode == wmsContainer.ContainerCode && p.BindStatus == CommonStatus.ENABLE).ToListAsync();
            await _wmsMaterialContainerRep.DeleteAsync(wmsMaterialContainerList);
            var orderNo = "N/A";
            if (input.WmsMaterials.Count > 0)
            {
                wmsContainer.ContainerStatus = ContainerStatus.ZUPANG;
                orderNo = YitIdHelper.NextId().ToString();
                await _wmsContainerRep.UpdateAsync(wmsContainer);
            }
            // 创建新组盘记录
            foreach (var item in input.WmsMaterials)
            {
                //创建组盘记录
                var bindentranceModel = new WmsMaterialContainer();
                bindentranceModel.ContainerId = wmsContainer.Id;
                bindentranceModel.ContainerCode = wmsContainer.ContainerCode;
                bindentranceModel.MaterialNo = item.MaterialNo;
                bindentranceModel.MaterialId = 478183507525701;
                bindentranceModel.MaterialBatch = item.MaterialBatch;
                bindentranceModel.BindQuantity = 1;
                bindentranceModel.BindStatus = CommonStatus.ENABLE;
                bindentranceModel.OrderNo = orderNo;
                bindentranceModel.MaterialName = item.MaterialName;
                bindentranceModel.MaterialDensity = "N/A";
                await _wmsMaterialContainerRep.InsertNowAsync(bindentranceModel);
            }
        }



        /// <summary>
        /// 自动入库
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("automaticWarehousing")]
        [UnitOfWork]
        public async Task AutomaticWarehousing(WarehousingInput input)
        {
            // 查询混合料库区信息
            var wmsArea = await _wmsAreaRep.FirstOrDefaultAsync(u => u.AreaName.Contains("绝缘立库"));
            // 根据料箱号查询周转箱号信息是否已存在
            var wmsContainer = await _wmsContainerRep.FirstOrDefaultAsync(u => u.ContainerCode == input.ContainerCode);
            if (wmsContainer == null)
            {
                // 不存在则添加周转箱号信息
                wmsContainer = new WmsContainer
                {
                    ContainerCode = input.ContainerCode,
                    ContainerType = ContainerType.JINSHU,
                    ContainerStatus = ContainerStatus.KOUXIAN,
                    AssetNo = "N/A",
                    ErpNo = "N/A"
                };
                await _wmsContainerRep.InsertNowAsync(wmsContainer);
            }
            else
            {
                // 更新周转箱号状态为“库位”
                wmsContainer.ContainerStatus = ContainerStatus.KOUXIAN;
                await _wmsContainerRep.UpdateAsync(wmsContainer);
            }

            // 查询周转箱号是否已存在任务
            var isWmsTask = await _wmsTaskRep.AnyAsync(p => p.ContainerCode == wmsContainer.ContainerCode && p.TaskStatus != TaskStatusEnum.WANCHENG);
            if (isWmsTask) throw Oops.Oh("周转箱号存在未完成任务中!");

            // 删除已组盘信息
            var oldWmsMaterialContainerList = await _wmsMaterialContainerRep
                .Where(p => p.ContainerCode == wmsContainer.ContainerCode && p.BindStatus == CommonStatus.ENABLE).ToListAsync();

            foreach (var item in oldWmsMaterialContainerList)
            {
                await _wmsMaterialContainerRep.DeleteAsync(item);
            }

            // 组盘单据 默认空料箱单据
            var source = ""; //定义入库来源
            var orderNo = "N/A";
            if (input.WmsMaterials.Count > 0)
            {
                wmsContainer.ContainerStatus = ContainerStatus.ZUPANG;
                orderNo = YitIdHelper.NextId().ToString();
                await _wmsContainerRep.UpdateAsync(wmsContainer);
                source = "物料";
            }
            else
            {
                source = "空托";
            }
            // 查询物料Id
            var wmsMaterial = await _wmsMaterialRep.FirstOrDefaultAsync(u => u.MaterialNo == "N/A" && u.MaterialName == "N/A" && u.MaterialBatch == "N/A");

            // 创建新组盘记录
            foreach (var item in input.WmsMaterials)
            {
                var wmsMaterialContainer = item.Adapt<WmsMaterialContainer>();
                wmsMaterialContainer.OrderNo = orderNo;
                wmsMaterialContainer.ContainerId = wmsContainer.Id;
                wmsMaterialContainer.ContainerCode = wmsContainer.ContainerCode;
                wmsMaterialContainer.MaterialId = wmsMaterial.Id;
                wmsMaterialContainer.BindStatus = CommonStatus.ENABLE;
                await _wmsMaterialContainerRep.InsertNowAsync(wmsMaterialContainer);
            }


            //if (input.Source == RuKuSourceEnum.KONGTUO)
            //else if (input.Source == RuKuSourceEnum.WULIAO)

            //创建巷道分配
            var wmsPlace = await _wmsPlaceRep.Where(u => u.PlaceStatus == PlaceStatus.KONGXIAN).ToListAsync();
            var one = wmsPlace.Where(s => s.Aisle==1).ToList().Count;
            var two = wmsPlace.Where(s => s.Aisle == 2).ToList().Count;
            var three = wmsPlace.Where(s => s.Aisle == 3).ToList().Count;
            var Aisle = 0;
            if (one >= two && one >= three)
            {
                Aisle = 1;
            }
            else if (two >= one && two >= three)
            {
                Aisle = 2;
            }
            else
            {
                Aisle = 3;
            }

            string taskNo = "RUKU"+ DateTime.Today.ToString("yyyyMMdd");
            var wmsTaskModel = await _wmsTaskRep.DetachedEntities.FirstOrDefaultAsync(u => EF.Functions.Like(u.TaskNo, $"%{taskNo}%"));
            if (wmsTaskModel == null)
            {
                taskNo = taskNo + "0001";
            }
            else
            {
                //获取流水号最大的数据
                var maxSerialNumber = await _wmsTaskRep.MaxAsync(t => t.TaskNo);
                taskNo = SysCommUtil.GenerateNewInvoiceNumber(maxSerialNumber, 1);
            }

            // 创建任务
            var takmodel = new WmsTask()
            {
                TaskNo = taskNo,//YitIdHelper.NextId().ToString(),
                TaskModel = TaskModel.QUANZIDONG,
                TaskType = TaskType.RUKU,
                TaskLevel = 1,
                Aisle = Aisle,
                TaskStatus = TaskStatusEnum.WEIZHIXING,
                ContainerCode = wmsContainer.ContainerCode,
                SourcePlace = "入库口",
                ToPlace = "",
                AreaName = wmsArea != null ? wmsArea.AreaName : "",
                OrderNo = orderNo,
                Description = source, //入库来源
                TaskDodeviceStatus = TaskDodeviceStatusEnum.WZX,
                IsRead = true
            };
            await _wmsTaskRep.InsertAsync(takmodel);
        }





        /// <summary>
        /// 人工入库
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("manualWarehousing")]
        [UnitOfWork]
        public async Task ManualWarehousing(WarehousingInput input)
        {
            // 查询混合料库区信息
            var wmsArea = await _wmsAreaRep.FirstOrDefaultAsync(u => u.AreaName.Contains("绝缘立库"));
            // 根据料箱号查询周转箱号信息是否已存在
            var wmsContainer = await _wmsContainerRep.FirstOrDefaultAsync(u => u.ContainerCode == input.ContainerCode);
            if (wmsContainer == null)
            {
                // 不存在则添加周转箱号信息
                wmsContainer = new WmsContainer
                {
                    ContainerCode = input.ContainerCode,
                    ContainerType = ContainerType.JINSHU,
                    ContainerStatus = ContainerStatus.KUWEI,
                    AssetNo = "N/A",
                    ErpNo = "N/A"
                };
                await _wmsContainerRep.InsertNowAsync(wmsContainer);
            }
            else
            {
                // 更新周转箱号状态为“库位”
                wmsContainer.ContainerStatus = ContainerStatus.KUWEI;
                await _wmsContainerRep.UpdateAsync(wmsContainer);
            }

            // 查询周转箱号是否已存在任务
            var isWmsTask = await _wmsTaskRep.AnyAsync(p => p.ContainerCode == wmsContainer.ContainerCode && p.TaskStatus != TaskStatusEnum.WANCHENG);
            if (isWmsTask) throw Oops.Oh("周转箱号存在未完成任务中!");

            // 删除已组盘信息
            var oldWmsMaterialContainerList = await _wmsMaterialContainerRep
                .Where(p => p.ContainerCode == wmsContainer.ContainerCode && p.BindStatus == CommonStatus.ENABLE).ToListAsync();

            foreach (var item in oldWmsMaterialContainerList)
            {
                await _wmsMaterialContainerRep.DeleteAsync(item);
            }

            // 查询库位信息 随机分配库位
            var wmsPlace = new WmsPlace();
            if (string.IsNullOrEmpty(input.PlaceCode))
                wmsPlace = await _wmsPlaceRep.FirstOrDefaultAsync(u => u.AreaId == wmsArea.Id && u.Islock == YesOrNot.N && u.PlaceStatus == PlaceStatus.KONGXIAN);
            else
                wmsPlace = await _wmsPlaceRep.FirstOrDefaultAsync(u => u.AreaId == wmsArea.Id && u.PlaceCode == input.PlaceCode);
            if (wmsPlace == null) throw Oops.Oh("库位不存在!");
            if (wmsPlace.Islock == YesOrNot.Y) throw Oops.Oh("库位被锁定!");
            if (wmsPlace.PlaceStatus != PlaceStatus.KONGXIAN) throw Oops.Oh("库位已存货!");
            // 更新库位状态为“存货”
            wmsPlace.PlaceStatus = PlaceStatus.CUNHUO;

            // 组盘单据 默认空料箱单据
            var orderNo = "N/A";
            var source = ""; //定义入库来源
            if (input.WmsMaterials.Count > 0)
            {
                orderNo = YitIdHelper.NextId().ToString();
                source = "物料";
            }
            else
            {
                wmsPlace.EmptyContainer = YesOrNot.Y;  //是否空托
                source = "空托";
            }
            // 查询物料Id
            var wmsMaterial = await _wmsMaterialRep.FirstOrDefaultAsync(u => u.MaterialNo == "N/A" && u.MaterialName == "N/A" && u.MaterialBatch == "N/A");

            // 创建新组盘记录
            foreach (var item in input.WmsMaterials)
            {
                var wmsMaterialContainer = item.Adapt<WmsMaterialContainer>();
                wmsMaterialContainer.OrderNo = orderNo;
                wmsMaterialContainer.ContainerId = wmsContainer.Id;
                wmsMaterialContainer.ContainerCode = wmsContainer.ContainerCode;
                wmsMaterialContainer.MaterialId = wmsMaterial.Id;
                wmsMaterialContainer.BindStatus = CommonStatus.ENABLE;

                await _wmsMaterialContainerRep.InsertNowAsync(wmsMaterialContainer);
            }

            string taskNo = "RUKU" + DateTime.Today.ToString("yyyyMMdd");
            var wmsTaskModel = await _wmsTaskRep.DetachedEntities.FirstOrDefaultAsync(u => EF.Functions.Like(u.TaskNo, $"%{taskNo}%"));
            if (wmsTaskModel == null)
            {
                taskNo = taskNo + "0001";
            }
            else
            {
                //获取流水号最大的数据
                var maxSerialNumber = await _wmsTaskRep.MaxAsync(t => t.TaskNo);
                taskNo = SysCommUtil.GenerateNewInvoiceNumber(maxSerialNumber, 1);
            }

            // 创建任务
            var takmodel = new WmsTask()
            {
                TaskNo = taskNo,//YitIdHelper.NextId().ToString(),
                TaskModel = TaskModel.SHOUDONG,
                TaskType = TaskType.RUKU,
                TaskLevel = 1,
                Aisle = wmsPlace.Aisle,
                TaskStatus = TaskStatusEnum.WANCHENG,
                ContainerCode = wmsContainer.ContainerCode,
                SourcePlace = "入库口",
                ToPlace = wmsPlace.PlaceCode,
                AreaName = wmsArea != null ? wmsArea.AreaName : "",
                OrderNo = orderNo,
                Description = source, //入库来源
                TaskDodeviceStatus = TaskDodeviceStatusEnum.W,
                UpdatedTime = DateTime.Now,
            };
            await _wmsTaskRep.InsertAsync(takmodel);

            // 创建托盘号库位关系表
            var wmsContainerPlaceModel = new WmsContainerPlace()
            {
                PlaceId = wmsPlace.Id,
                PlaceCode = wmsPlace.PlaceCode,
                ContainerId = wmsContainer.Id,
                ContainerCode = wmsContainer.ContainerCode,
                ContainerPlaceStatus = CommonStatus.ENABLE
            };
            await _wmsContainerPlaceRep.InsertAsync(wmsContainerPlaceModel);

            // 更新库存
            var wmsMaterialContainerList = await _wmsMaterialContainerRep.DetachedEntities
                .Where(p => p.OrderNo == orderNo && p.BindStatus == CommonStatus.ENABLE).ProjectToType<WmsMaterialContainer>().ToListAsync();

            foreach (var item in wmsMaterialContainerList)
            {
                var wmsMaterialStock = await _wmsMaterialStockRep.FirstOrDefaultAsync(p => p.ContainerCode == wmsContainer.ContainerCode
                && p.MaterialBatch == item.MaterialBatch );
                if (wmsMaterialStock != null)
                {
                    wmsMaterialStock.Source = RuKuSourceEnum.WULIAO;
                    wmsMaterialStock.AreaId = wmsPlace.AreaId;
                    wmsMaterialStock.PlaceCode = wmsPlace.PlaceCode;
                    wmsMaterialStock.StockNumber += item.BindQuantity;
                    await _wmsMaterialStockRep.UpdateAsync(wmsMaterialStock);
                }
                else
                {
                    wmsMaterialStock = new WmsMaterialStock()
                    {
                        InspectionMethod = MaterialInspection.MIANJIAN,
                        UnitType = UnitType.ZHONGLIANG,
                        UnitNo = UnitNoType.T,
                        MaterialNo = item.MaterialNo,
                        MaterialType = MaterialType.CHENGPING,
                        MaterialName = item.MaterialName,
                        MaterialSpec = item.MaterialSpec,
                        MaterialBatch = item.MaterialBatch,
                        MaterialDensity = item.MaterialDensity,
                        StockNumber = 1,
                        PlaceCode = wmsPlace.PlaceCode,
                        ContainerId = wmsContainer.Id,
                        ContainerCode = wmsContainer.ContainerCode,
                        AreaId = wmsPlace.AreaId,
                        Source = RuKuSourceEnum.WULIAO
                };
                    await _wmsMaterialStockRep.InsertAsync(wmsMaterialStock);
                }
            }
            // 空料箱入库
            if (orderNo == "N/A")
            {
                var wmsMaterialStock = new WmsMaterialStock()
                {
                    InspectionMethod = MaterialInspection.MIANJIAN,
                    UnitType = UnitType.ZHONGLIANG,
                    UnitNo = UnitNoType.T,
                    MaterialNo = "N/A",
                    MaterialType = MaterialType.KONGTUO,
                    MaterialName = "N/A",
                    MaterialSpec = "N/A",
                    MaterialBatch = "N/A",
                    MaterialDensity = "N/A",
                    StockNumber = 0,
                    PlaceCode = wmsPlace.PlaceCode,
                    ContainerId = wmsContainer.Id,
                    ContainerCode = wmsContainer.ContainerCode,
                    AreaId = wmsPlace.AreaId,
                    Source = RuKuSourceEnum.KONGTUO
            };
                await _wmsMaterialStockRep.InsertAsync(wmsMaterialStock);
            }
        }
    }
}